package com.glq1218.permission.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glq1218.domain.*;
import com.glq1218.permission.bo.AddPermissionBO;
import com.glq1218.permission.bo.PermissionBO;
import com.glq1218.permission.bo.QueryPermissionBO;
import com.glq1218.permission.bo.UpdatePermissionBO;
import com.glq1218.permission.entity.Permission;
import com.glq1218.permission.mapper.PermissionMapper;
import com.glq1218.permission.service.PermissionService;
import com.glq1218.util.BeanCopyUtils;
import com.glq1218.util.SecurityUtils;
import com.glq1218.util.ServiceUtils;
import com.glq1218.util.SortUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author glq1218
 * @description TODO
 * @since 2023/4/18 15:08
 */
@Service("permissionService")
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {
    @Override
    public PaginationResult<PermissionBO> queryPermissionList(PaginationParam paginationParam, SortParam sortParam, IntervalStr intervalStr, QueryPermissionBO queryPermissionBO) {
        // 处理时间间隔
        Interval interval = ServiceUtils.getInterval(intervalStr);
        // 分页对象
        Page<Permission> permissionPage = ServiceUtils.getPage(paginationParam);
        // 构建查询条件对象
        String sortSql = "";
        if (StringUtils.hasText(sortParam.getSortField())) {
            sortSql = SortUtils.getSortSql(sortParam);
        }
        LambdaQueryWrapper<Permission> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper
                .like(StringUtils.hasText(queryPermissionBO.getName()), Permission::getName, queryPermissionBO.getName())
                .like(StringUtils.hasText(queryPermissionBO.getPermissionKey()), Permission::getPermissionKey, queryPermissionBO.getPermissionKey())
                .eq(StringUtils.hasText(queryPermissionBO.getType()), Permission::getType, queryPermissionBO.getType())
                .eq(queryPermissionBO.getStatus() != null, Permission::getStatus, queryPermissionBO.getStatus())
                .between(StringUtils.hasText(intervalStr.getUpdatedAtStart()) && StringUtils.hasText(intervalStr.getUpdatedAtEnd()),
                        Permission::getUpdatedAt, interval.getUpdatedAtStart(), interval.getUpdatedAtEnd())
                .between(StringUtils.hasText(intervalStr.getCreatedAtStart()) && StringUtils.hasText(intervalStr.getCreatedAtEnd()), Permission::getCreatedAt, interval.getCreatedAtStart(), interval.getCreatedAtEnd())
                // 默认就是使用主键id进行升序排序，可以配置其他字段，如修改日期等
                // .orderBy(!StringUtils.hasText(sortParam.getSortOrder()), true, Permission::getId)
                .last(StringUtils.hasText(sortParam.getSortField()) && StringUtils.hasText(sortParam.getSortOrder()), sortSql);
        // 分页查询
        page(permissionPage, lambdaQueryWrapper);
        // 获取总数，如果总数为0，就直接返回
        long total = permissionPage.getTotal();
        if (total == 0L) {
            return PaginationResult.<PermissionBO>builder().total(0L).build();
        }
        // 将Permission转为PermissionBO并设置角色信息
        List<Permission> permissionList = permissionPage.getRecords();
        List<PermissionBO> permissionBOList = BeanCopyUtils.copyBeanList(permissionList, PermissionBO.class);
        return PaginationResult.<PermissionBO>builder().total(total).records(permissionBOList)
                .build();
    }

    @Override
    public List<RolePermission> queryAllPermission() {
        LambdaQueryWrapper<Permission> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(Permission::getType, "P");
        List<Permission> permissions = getBaseMapper().selectList(lambdaQueryWrapper);

        if (permissions == null) {
            permissions = new ArrayList<>();
        }
        return permissions.stream().map(permission -> new RolePermission(permission.getId(), permission.getName())).toList();
    }

    /**
     * 根据权限id获取权限信息
     *
     * @param id 权限id
     * @return 权限信息
     */
    @Override
    public PermissionBO getPermissionById(Serializable id) {
        Permission permission = getById(id);
        if (Objects.isNull(permission)) {
            return null;
        }
        return BeanCopyUtils.copyBean(permission, PermissionBO.class);
    }

    /**
     * 新增权限信息
     *
     * @param addPermissionBO 新增权限业务对象
     * @return 操作结果
     */
    @Override
    public String addPermission(AddPermissionBO addPermissionBO) {
        Permission permission = BeanCopyUtils.copyBean(addPermissionBO, Permission.class);
        boolean saved = save(permission);
        if (saved) {
            return "新增成功";
        }
        throw new RuntimeException("新增失败");
    }

    /**
     * 更新权限信息
     *
     * @param updatePermissionBO 跟新权限业务对象
     * @return 是否封信成功
     */
    @Override
    public String updatePermission(UpdatePermissionBO updatePermissionBO) {
        Permission permission = BeanCopyUtils.copyBean(updatePermissionBO, Permission.class);
        boolean update = updateById(permission);
        if (update) {
            return "更新成功";
        }
        throw new RuntimeException("更新失败");
    }

    @Override
    public List<MenuTree> queryMenuTree() {
        Long userId = SecurityUtils.getUserId();
        if (userId == 1L) {
            LambdaQueryWrapper<Permission> topQueryWrapper = Wrappers.lambdaQuery();
            topQueryWrapper.eq(Permission::getType, "M").eq(Permission::getPId, 0L);
            List<Permission> topPermissions = getBaseMapper().selectList(topQueryWrapper);
            LambdaQueryWrapper<Permission> subQueryWrapper = Wrappers.lambdaQuery();
            subQueryWrapper.eq(Permission::getType, "M").ne(Permission::getPId, 0L);
            List<Permission> subPermissions = getBaseMapper().selectList(subQueryWrapper);
            return generateMenuTree(
                    topPermissions.stream().map(permission -> new Menu(permission.getId(), permission.getName(), permission.getIcon(), permission.getPath(), permission.getPId())).collect(Collectors.toList()),
                    subPermissions.stream().map(permission -> new Menu(permission.getId(), permission.getName(), permission.getIcon(), permission.getPath(), permission.getPId())).collect(Collectors.toList())
            );
        }
        List<Menu> pMenuList = getBaseMapper().queryTopMenuListByUserId(userId);
        List<Menu> sMenuList = getBaseMapper().querySubMenuListByUserId(userId);
        return generateMenuTree(pMenuList, sMenuList);
    }

    @Override
    public List<MenuTree> queryTopMenuTree() {
        List<Menu> pMenuList = getBaseMapper().queryTopMenuList();
        List<Menu> sMenuList = getBaseMapper().querySubMenuList();
        return generateMenuTree(pMenuList, sMenuList);
    }

    @Override
    public Set<String> queryPermissionByUserId(Long userId) {
        if (userId == 1L) {
            LambdaQueryWrapper<Permission> lambdaQueryWrapper = Wrappers.lambdaQuery();
            lambdaQueryWrapper.eq(Permission::getType, "P");
            return list(lambdaQueryWrapper).parallelStream().map(Permission::getPermissionKey).collect(Collectors.toSet());
        }
        return getBaseMapper().queryPermissionByUserId(userId);
    }

    private List<MenuTree> generateMenuTree(List<Menu> pMenuList, List<Menu> sMenuList) {
        List<MenuTree> menuTreeList = BeanCopyUtils.copyBeanList(pMenuList, MenuTree.class);
        menuTreeList = menuTreeList.stream().peek(menuTree -> {
            List<MenuTree> menuTrees = new ArrayList<>();
            sMenuList.forEach(sMenu -> {
                if (menuTree.getId().equals(sMenu.getPId())) {
                    MenuTree copiedBean = BeanCopyUtils.copyBean(sMenu, MenuTree.class);
                    menuTrees.add(copiedBean);
                }
                menuTree.setChildren(menuTrees);
            });
        }).collect(Collectors.toList());
        return menuTreeList;
    }
}
